package com.jason.measure.view;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;

/**
 * @Author: Jason
 * @Date: 2016/11/1
 * @Time: 10:47.
 */

public class SquareLayout5 extends ViewGroup {

    private static final String TAG = SquareLayout5.class.getSimpleName();

    private static final int ORIENTATION_HORIZONTAL = 0, ORIENTATION_VERTICAL = 1; // 排列方向的常量
    private static final int DEFAULT_MAX_ROW = Integer.MAX_VALUE, DEFAULT_MAX_COLUMN = Integer.MAX_VALUE; // 最大行列默认值

    private int mMaxRow = DEFAULT_MAX_ROW; // 最大行数
    private int mMaxColumn = DEFAULT_MAX_COLUMN; // 最大列数

    private int mOrientation = ORIENTATION_VERTICAL; // 排列方向


    public SquareLayout5(Context context, AttributeSet attrs) {
        super(context, attrs);
        mMaxRow = mMaxColumn = 2;
    }


    /**
     *  让子元素的margins外边距能够被正确的计算,必须重写三个方法
     */
    @Override
    protected LayoutParams generateDefaultLayoutParams() {
        Log.e(TAG, "---generateDefaultLayoutParams---");
        return new MarginLayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
    }

    @Override
    protected LayoutParams generateLayoutParams(LayoutParams p) {
        Log.e(TAG, "---generateLayoutParams--p---");
        return new MarginLayoutParams(p);
    }

    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        Log.e(TAG, "---checkLayoutParams---attrs---");
        return new MarginLayoutParams(getContext(), attrs);
    }

    // 重写 checkLayoutParams验证当前LayoutParams对象是否为MarginLayoutParams的实例
    @Override
    protected boolean checkLayoutParams(LayoutParams p) {
        Log.e(TAG, "---checkLayoutParams---");
        return p instanceof MarginLayoutParams;
    }




    // 测量控件
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        Log.e(TAG, "---onMeasure---");

        // 声明临时变量存储父容器的期望值 该值应该等于父容器的内边距加上所有子元素的测量宽高和外边距
        int parentDesireWidth = 0;
        int parentDesireHeight = 0;

        // 声明临时变量存储子元素的测量状态
        int childMeasureState = 0;

        // 容器有子元素
        if (getChildCount() > 0) {
            // 遍历子元素
            for (int i = 0; i < getChildCount(); i++) {
                View child = getChildAt(i);

                // 如果该子元素没有以"不占用空间"的方式隐藏则表示需要被测量计算
                if (child.getVisibility() != View.GONE) {
                    // 测量子元素并考量其外边距
                    measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);
                    // 比较子元素测量宽高并比较取其较大值
                    int childMeasureSize = Math.max(child.getMeasuredWidth(), child.getMeasuredHeight());
                    // 重新封装子元素测量规格
                    int childMeasureSpec = MeasureSpec.makeMeasureSpec(childMeasureSize, MeasureSpec.EXACTLY);

                    // 重新测量子元素
                    child.measure(childMeasureSpec, childMeasureSpec);

                    // 获取子元素布局参数
                    MarginLayoutParams mlp = (MarginLayoutParams) child.getLayoutParams();

                    // 考量外边距计算子元素实际宽高
                    int childActualWidth = child.getMeasuredWidth() + mlp.leftMargin + mlp.rightMargin;
                    int childActualHeight = child.getMeasuredHeight() + mlp.topMargin + mlp.bottomMargin;

                    // 如果为横向排列
                    if (mOrientation == ORIENTATION_HORIZONTAL) {
                        // 累加子元素的实际宽度
                        parentDesireWidth += childActualWidth;
                        // 获取子元素中高度最大值
                        parentDesireHeight = Math.max(parentDesireHeight, childActualHeight);

                    } else { // 竖向排列
                        // 累加子元素的实际高度
                        parentDesireHeight += childActualHeight;
                        parentDesireWidth = Math.max(parentDesireWidth, childActualWidth);

                    }

                    // 合并子元素的测量状态
                    childMeasureState = combineMeasuredStates(childMeasureState, child.getMeasuredState());

                }

            }

            // 考量父容器内边距将其累加到期望值
            parentDesireWidth += getPaddingLeft() + getPaddingRight();
            parentDesireHeight += getPaddingTop() + getPaddingBottom();

            // 尝试比较父容器期望值与Android建议的最小值大小并取较大值
            parentDesireWidth = Math.max(parentDesireWidth, getSuggestedMinimumWidth());
            parentDesireHeight = Math.max(parentDesireHeight, getSuggestedMinimumHeight());
        }

        // 确定容器的测量宽高
        setMeasuredDimension(resolveSizeAndState(parentDesireWidth, widthMeasureSpec, childMeasureState),
                resolveSizeAndState(parentDesireHeight, heightMeasureSpec, childMeasureState << MEASURED_HEIGHT_STATE_SHIFT));

    }


    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {

        Log.e(TAG, "---onLayout---");

        if (getChildCount() > 0) {
            // 声明临时变量存储宽高倍增值
            int multi = 0;

            for (int i = 0; i < getChildCount(); i++) {
                // 获取对应的子元素
                View child = getChildAt(i);

                // 如果该子元素没有以"不占用空间"的方式隐藏则表示其需要被测量计算
                if (child.getVisibility() != View.GONE) {
                    // 获取子元素布局参数
                    MarginLayoutParams mlp = (MarginLayoutParams) child.getLayoutParams();

                    // 获取控件尺寸
                    int childActualSize = child.getMeasuredWidth();

                    // 如果为横向排列
                    if (mOrientation == ORIENTATION_HORIZONTAL) {
                        // 确定子元素 左上 右下坐标
                        child.layout(getPaddingLeft() + mlp.leftMargin + multi,
                                getPaddingTop() + mlp.topMargin,
                                childActualSize + getPaddingLeft() + mlp.leftMargin + multi,
                                childActualSize + getPaddingTop() + mlp.topMargin);

                        // 累加倍增值
                        multi += childActualSize + mlp.leftMargin + mlp.rightMargin;

                    } else { // 竖向排列

                        child.layout(getPaddingLeft() + mlp.leftMargin,
                                getPaddingTop() + mlp.topMargin + multi,
                                childActualSize + getPaddingLeft() + mlp.leftMargin,
                                childActualSize + getPaddingTop() + mlp.topMargin + multi);

                        multi += childActualSize + mlp.topMargin + mlp.bottomMargin;

                    }
                }

            }
        }


    }
}







